summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorliamwhite <liamwhite@users.noreply.github.com>2023-12-16 17:47:03 +0100
committerGitHub <noreply@github.com>2023-12-16 17:47:03 +0100
commitfde8dc1652aa886210a9fa45bf2b859e14c11b37 (patch)
treebbea883a222d556a8a917f70ec384cac5f6efcff
parentMerge pull request #12359 from german77/real_shared (diff)
parentcommon: use memory holepunching when clearing memory (diff)
downloadyuzu-fde8dc1652aa886210a9fa45bf2b859e14c11b37.tar
yuzu-fde8dc1652aa886210a9fa45bf2b859e14c11b37.tar.gz
yuzu-fde8dc1652aa886210a9fa45bf2b859e14c11b37.tar.bz2
yuzu-fde8dc1652aa886210a9fa45bf2b859e14c11b37.tar.lz
yuzu-fde8dc1652aa886210a9fa45bf2b859e14c11b37.tar.xz
yuzu-fde8dc1652aa886210a9fa45bf2b859e14c11b37.tar.zst
yuzu-fde8dc1652aa886210a9fa45bf2b859e14c11b37.zip
-rw-r--r--src/common/host_memory.cpp38
-rw-r--r--src/common/host_memory.h2
-rw-r--r--src/core/hle/kernel/k_memory_manager.cpp5
-rw-r--r--src/core/hle/kernel/k_page_table_base.cpp14
4 files changed, 42 insertions, 17 deletions
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 4bfc64f2d..e540375b8 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -11,10 +11,6 @@
#elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv
-#ifdef ANDROID
-#include <android/sharedmem.h>
-#endif
-
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
@@ -193,6 +189,11 @@ public:
}
}
+ bool ClearBackingRegion(size_t physical_offset, size_t length) {
+ // TODO: This does not seem to be possible on Windows.
+ return false;
+ }
+
void EnableDirectMappedAddress() {
// TODO
UNREACHABLE();
@@ -442,9 +443,7 @@ public:
}
// Backing memory initialization
-#ifdef ANDROID
- fd = ASharedMemory_create("HostMemory", backing_size);
-#elif defined(__FreeBSD__) && __FreeBSD__ < 13
+#if defined(__FreeBSD__) && __FreeBSD__ < 13
// XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
fd = shm_open(SHM_ANON, O_RDWR, 0600);
#else
@@ -455,7 +454,6 @@ public:
throw std::bad_alloc{};
}
-#ifndef ANDROID
// Defined to extend the file with zeros
int ret = ftruncate(fd, backing_size);
if (ret != 0) {
@@ -463,7 +461,6 @@ public:
strerror(errno));
throw std::bad_alloc{};
}
-#endif
backing_base = static_cast<u8*>(
mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
@@ -552,6 +549,19 @@ public:
ASSERT_MSG(ret == 0, "mprotect failed: {}", strerror(errno));
}
+ bool ClearBackingRegion(size_t physical_offset, size_t length) {
+#ifdef __linux__
+ // Set MADV_REMOVE on backing map to destroy it instantly.
+ // This also deletes the area from the backing file.
+ int ret = madvise(backing_base + physical_offset, length, MADV_REMOVE);
+ ASSERT_MSG(ret == 0, "madvise failed: {}", strerror(errno));
+
+ return true;
+#else
+ return false;
+#endif
+ }
+
void EnableDirectMappedAddress() {
virtual_base = nullptr;
}
@@ -623,6 +633,10 @@ public:
void Protect(size_t virtual_offset, size_t length, bool read, bool write, bool execute) {}
+ bool ClearBackingRegion(size_t physical_offset, size_t length) {
+ return false;
+ }
+
void EnableDirectMappedAddress() {}
u8* backing_base{nullptr};
@@ -698,6 +712,12 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w
impl->Protect(virtual_offset + virtual_base_offset, length, read, write, execute);
}
+void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value) {
+ if (!impl || fill_value != 0 || !impl->ClearBackingRegion(physical_offset, length)) {
+ std::memset(backing_base + physical_offset, fill_value, length);
+ }
+}
+
void HostMemory::EnableDirectMappedAddress() {
if (impl) {
impl->EnableDirectMappedAddress();
diff --git a/src/common/host_memory.h b/src/common/host_memory.h
index cebfacab2..747c5850c 100644
--- a/src/common/host_memory.h
+++ b/src/common/host_memory.h
@@ -48,6 +48,8 @@ public:
void EnableDirectMappedAddress();
+ void ClearBackingRegion(size_t physical_offset, size_t length, u32 fill_value);
+
[[nodiscard]] u8* BackingBasePointer() noexcept {
return backing_base;
}
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp
index 0a973ec8c..d6bd27296 100644
--- a/src/core/hle/kernel/k_memory_manager.cpp
+++ b/src/core/hle/kernel/k_memory_manager.cpp
@@ -421,8 +421,9 @@ Result KMemoryManager::AllocateForProcess(KPageGroup* out, size_t num_pages, u32
} else {
// Set all the allocated memory.
for (const auto& block : *out) {
- std::memset(m_system.DeviceMemory().GetPointer<void>(block.GetAddress()), fill_pattern,
- block.GetSize());
+ m_system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(block.GetAddress()) -
+ Core::DramMemoryMap::Base,
+ block.GetSize(), fill_pattern);
}
}
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp
index 4c416d809..423289145 100644
--- a/src/core/hle/kernel/k_page_table_base.cpp
+++ b/src/core/hle/kernel/k_page_table_base.cpp
@@ -81,6 +81,11 @@ void InvalidateInstructionCache(KernelCore& kernel, AddressType addr, u64 size)
}
}
+void ClearBackingRegion(Core::System& system, KPhysicalAddress addr, u64 size, u32 fill_value) {
+ system.DeviceMemory().buffer.ClearBackingRegion(GetInteger(addr) - Core::DramMemoryMap::Base,
+ size, fill_value);
+}
+
template <typename AddressType>
Result InvalidateDataCache(AddressType addr, u64 size) {
R_SUCCEED();
@@ -1363,8 +1368,7 @@ Result KPageTableBase::MapInsecureMemory(KProcessAddress address, size_t size) {
// Clear all the newly allocated pages.
for (const auto& it : pg) {
- std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()),
- static_cast<u32>(m_heap_fill_value), it.GetSize());
+ ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);
}
// Lock the table.
@@ -1570,8 +1574,7 @@ Result KPageTableBase::AllocateAndMapPagesImpl(PageLinkedList* page_list, KProce
// Clear all pages.
for (const auto& it : pg) {
- std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()),
- static_cast<u32>(m_heap_fill_value), it.GetSize());
+ ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);
}
// Map the pages.
@@ -2159,8 +2162,7 @@ Result KPageTableBase::SetHeapSize(KProcessAddress* out, size_t size) {
// Clear all the newly allocated pages.
for (const auto& it : pg) {
- std::memset(GetHeapVirtualPointer(m_kernel, it.GetAddress()), m_heap_fill_value,
- it.GetSize());
+ ClearBackingRegion(m_system, it.GetAddress(), it.GetSize(), m_heap_fill_value);
}
// Map the pages.